import { defineStore } from 'pinia'
import { v4 as uid } from 'uuid';
import { cloneDeep } from 'lodash'




// 定义组件样式接口
interface ComponentStyle {
    visible: boolean
    transform: number
    borderWidth: number
    borderStyle: 'solid' | 'dashed' | 'dotted' | string
    borderColor: string
    position: {
        x: number
        y: number
    }
    [key: string]: any // 允许其他样式属性
}

// 定义拓扑组件接口
interface TopoComponent {
    identifier: string
    type: string
    name: string
    style: ComponentStyle
    [key: string]: any // 允许其他组件属性
}

// 定义拓扑数据接口
interface TopoData {
    components: TopoComponent[]
    layer: Record<string, any>
}


// 定义命令接口
interface CommandBase {
    op: string
    backup?: any
}

interface AddCommand extends CommandBase {
    op: 'add'
    component: Omit<TopoComponent, 'identifier' | 'name' | 'style'> & {
        style?: Partial<ComponentStyle>
    }
    identifier: string // 新增：存储生成的ID用于撤销
}

interface DeleteCommand extends CommandBase {
    op: 'del'
    identifiers: string[] // 新增：明确存储要删除的ID
    backup?: TopoComponent[]
}

interface MoveCommand extends CommandBase {
    op: 'move'
    items: Record<string, TopoComponent>
    dx: number
    dy: number
    backup?: Record<string, { x: number; y: number }>
}

interface CopyAddCommand extends CommandBase {
    op: 'copy-add'
    items: TopoComponent[]
    backup?: string[]
}

interface UpdateStyleCommand extends CommandBase {
    op: 'update-style'
    component: TopoComponent
    changes: Partial<ComponentStyle>
    backup?: ComponentStyle
}

type Command = AddCommand | DeleteCommand | MoveCommand | CopyAddCommand | UpdateStyleCommand

export const useTopoEditorStore = defineStore('topoEditor', {
    state: (): {
        topoData: TopoData
        selectedComponents: string[]
        selectedComponentMap: Record<string, TopoComponent>
        selectedComponent: TopoComponent | null
        selectedIsLayer: boolean
        undoStack: Command[]
        redoStack: Command[]
        copySrcItems: TopoComponent[]
        copyCount: number
    } => ({
        topoData: { components: [], layer: {} },
        selectedComponents: [],
        selectedComponentMap: {},
        selectedComponent: null,
        selectedIsLayer: false,
        undoStack: [],
        redoStack: [],
        copySrcItems: [],
        copyCount: 0
    }),

    getters: {
        // 辅助获取选中的组件列表
        selectedComponentsList(): TopoComponent[] {
            return this.selectedComponents.map(id => this.selectedComponentMap[id]).filter(Boolean)
        },

        // 检查是否可以撤销
        canUndo(): boolean {
            return this.undoStack.length > 0
        },

        // 检查是否可以重做
        canRedo(): boolean {
            return this.redoStack.length > 0
        }
    },

    actions: {
        // 执行编辑命令（完善撤销支持）
        execute(command: Command) {
            if (!command) return;

            try {
                switch (command.op) {
                    case 'add': {

                        // 先处理样式的默认值和合并
                        const baseStyle: ComponentStyle = {
                            visible: true,
                            transform: 0,
                            borderWidth: 0,
                            borderStyle: 'solid',
                            borderColor: '#ccccccff',
                            position: { x: 0, y: 0 }
                        };
                        // 合并用户提供的样式
                        const mergedStyle: ComponentStyle = {
                            ...baseStyle,
                            ...(command.component.style || {}),
                            position: {
                                ...baseStyle.position,
                                ...(command.component.style?.position || {})
                            }
                        };


                        // 创建组件，明确指定type属性
                        const component: TopoComponent = {
                            ...command.component,
                            identifier: uid(),
                            // 确保type从command.component中获取，这里添加类型断言确保存在
                            type: command.component.type,
                            name: `${command.component.type}${this.topoData.components.length}`,
                            style: mergedStyle
                        };
                        // 保存生成的ID用于撤销
                        (command as AddCommand).identifier = component.identifier,
                            this.topoData.components.push(component)
                        this.setSelectedComponent(component)
                        break
                    }

                    case 'del': {
                        // 保存删除前的状态用于撤销
                        const deleteCommand = command as DeleteCommand
                        deleteCommand.identifiers = this.selectedComponents

                        deleteCommand.backup = cloneDeep(
                            this.topoData.components.filter(item => deleteCommand.identifiers.includes(item.identifier))
                        )

                        // 从组件列表中删除选中项
                        this.topoData.components = this.topoData.components.filter(
                            item => !deleteCommand.identifiers.includes(item.identifier)
                        )

                        this.clearSelectedComponent()
                        break
                    }

                    case 'move': {
                        // 保存移动前的位置
                        if (!command.backup) {
                            command.backup = Object.fromEntries(
                                Object.entries(command.items).map(([key, item]) => [
                                    key, { x: item.style.position.x, y: item.style.position.y }
                                ])
                            )
                        }

                        Object.values(command.items).forEach(component => {
                            component.style.position.x += command.dx
                            component.style.position.y += command.dy
                        })
                        break
                    }

                    case 'copy-add': {
                        this.clearSelectedComponent()
                        const newItems: TopoComponent[] = []

                        command.items.forEach(original => {
                            const component = cloneDeep(original) as TopoComponent
                            component.identifier = uid()
                            component.name = `${component.type}${this.topoData.components.length}`
                            component.style.position.x += 25 * (this.copyCount + 1)
                            component.style.position.y += 25 * (this.copyCount + 1)

                            this.topoData.components.push(component)
                            this.addSelectedComponent(component)
                            newItems.push(component)
                        })

                        command.backup = newItems.map(item => item.identifier)
                        this.copyCount++
                        break
                    }

                    case 'update-style': {
                        // 确保备份存在
                        if (!command.backup) {
                            command.backup = cloneDeep(command.component.style)
                        }

                        Object.assign(command.component.style, command.changes)
                        break
                    }
                }

                // 只有新命令才加入撤销栈
                this.undoStack.push(command)
                this.redoStack = [] // 新操作清空重做栈
            } catch (error) {
                console.error('执行命令失败:', error)
                // 可以在这里添加错误恢复逻辑
            }
        },

        // 完善撤销功能
        undo() {
            if (!this.canUndo) return

            const command = this.undoStack.pop()
            if (!command) return

            try {
                switch (command.op) {
                    case 'add': {
                        // 使用存储的ID删除
                        const addCommand = command as AddCommand
                        this.topoData.components = this.topoData.components.filter(
                            item => item.identifier !== addCommand.identifier
                        )
                        this.clearSelectedComponent()
                        break
                    }

                    case 'del': {
                        const deleteCommand = command as DeleteCommand
                        // 恢复删除的组件
                        if (deleteCommand.backup && Array.isArray(deleteCommand.backup)) {
                            deleteCommand.backup.forEach((item: TopoComponent) => {
                                // 检查是否已存在，避免重复添加
                                if (!this.topoData.components.some(c => c.identifier === item.identifier)) {
                                    this.topoData.components.push(item)
                                    this.addSelectedComponent(item)
                                }
                            })
                        }
                        break
                    }

                    case 'move': {
                        // 恢复原始位置
                        if (command.backup) {
                            Object.entries(command.backup as Record<string, { x: number; y: number }>).forEach(([key, pos]) => {
                                const component = (command as MoveCommand).items[key]
                                if (component) {
                                    component.style.position.x = pos.x
                                    component.style.position.y = pos.y
                                }
                            })
                        }
                        break
                    }

                    case 'copy-add': {
                        // 删除复制新增的组件
                        if (command.backup && Array.isArray(command.backup)) {
                            this.topoData.components = this.topoData.components.filter(
                                item => !(command.backup as string[]).includes(item.identifier)
                            )
                            this.clearSelectedComponent()
                            this.copyCount = Math.max(0, this.copyCount - 1)
                        }
                        break
                    }

                    case 'update-style': {
                        // 恢复原始样式
                        if (command.backup) {
                            Object.assign(
                                (command as UpdateStyleCommand).component.style,
                                (command as UpdateStyleCommand).backup
                            )
                        }
                        break
                    }
                }

                this.redoStack.push(command)
            } catch (error) {
                console.error('撤销操作失败:', error)
                // 出错时将命令放回撤销栈
                this.undoStack.push(command)
            }
        },

        // 完善重做功能
        redo() {
            if (!this.canRedo) return

            const command = this.redoStack.pop()
            if (command) {
                // 执行前先保存当前状态作为新的撤销点
                const clonedCommand = cloneDeep(command)
                this.execute(clonedCommand)
            }
        },

        // 选中组件操作
        setSelectedComponent(component: TopoComponent) {
            if (!component?.identifier) return

            this.selectedComponents = [component.identifier]
            this.selectedComponentMap = { [component.identifier]: component }
            this.selectedComponent = component
        },

        addSelectedComponent(component: TopoComponent) {
            if (!component?.identifier) return

            if (this.selectedComponentMap[component.identifier]) return

            this.selectedComponents.push(component.identifier)
            this.selectedComponentMap[component.identifier] = component
            this.selectedComponent = this.selectedComponents.length === 1
                ? component
                : null
        },

        removeSelectedComponent(component: TopoComponent) {
            if (!component?.identifier) return

            const index = this.selectedComponents.indexOf(component.identifier)
            if (index > -1) {
                this.selectedComponents.splice(index, 1)
                delete this.selectedComponentMap[component.identifier]
            }

            // 更新选中的单个组件
            if (this.selectedComponent?.identifier === component.identifier) {
                this.selectedComponent = this.selectedComponents.length
                    ? this.selectedComponentMap[this.selectedComponents[0]]
                    : null
            }
        },

        clearSelectedComponent() {
            this.selectedComponents = []
            this.selectedComponentMap = {}
            this.selectedComponent = null
        },

        // 复制选中的组件到剪贴板
        copySelectedComponents() {
            this.copySrcItems = this.selectedComponentsList
            this.copyCount = 0
        },

        // 粘贴复制的组件
        pasteCopiedComponents() {
            if (this.copySrcItems.length === 0) return

            this.execute({
                op: 'copy-add',
                items: this.copySrcItems
            })
        },

        // 加载默认拓扑数据
        async loadDefaultTopoData() {
            try {
                const json = await import('@/assets/data/topo-data.json')
                this.topoData = cloneDeep(json.default as TopoData)
                this.clearSelectedComponent()
                this.undoStack = []
                this.redoStack = []
            } catch (error) {
                console.error('加载默认拓扑数据失败:', error)
                // 提供默认 fallback
                this.topoData = { components: [], layer: {} }
            }
        }
    }
})
